package com.tensquare.notice.netty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.tensquare.notice.config.ApplicationContextProvider;
import entity.Result;
import entity.StatusCode;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import javafx.scene.media.SubtitleTrack;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;

import java.util.HashMap;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 用来处理websocket的请求的类，来完成具体的操作内容，是核心类
 * */
public class MyWebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static ObjectMapper MAPPER = new ObjectMapper();

    // 从Spring容器中获取消息监听器容器,处理订阅消息sysNotice
    SimpleMessageListenerContainer sysNoticeContainer = (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
            .getBean("sysNoticeContainer");
    // 从Spring容器中获取消息监听器容器,处理点赞消息userNotice
    SimpleMessageListenerContainer userNoticeContainer = (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
            .getBean("userNoticeContainer");
    //从Spring容器中获取消息监听器容器，处理喜欢消息loveNotice
    SimpleMessageListenerContainer loveNoticeContainer = (SimpleMessageListenerContainer) ApplicationContextProvider.getApplicationContext()
            .getBean("loveNoticeContainer");

    //从Spring容器中获取RabbitTemplate
    RabbitTemplate rabbitTemplate = ApplicationContextProvider.getApplicationContext().getBean(RabbitTemplate.class);

    //存放WebSocket连接Map，根据用户id存放
    public static ConcurrentHashMap<String, Channel> userChannelMap = new ConcurrentHashMap();

    //用户请求WebSocket服务端，执行的方法
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //约定用户第一次请求携带的数据：{"userId":"uid"}
        //获取用户请求数据并解析
        String json = msg.text();
        //解析json数据，获取用户id
        String userId = MAPPER.readTree(json).get("userId").asText();

        System.out.println("json:"+json);
        System.out.println("userId:"+userId);
        //第一次请求的时候，需要建立WebSocket连接
/*        Channel channel = userChannelMap.get(userId);
        if (channel == null) {
            //获取WebSocket的连接
            channel = ctx.channel();

            //把连接放到容器中
            userChannelMap.put(userId, channel);
            System.out.println("用户连接容器建立成功！");
        }*/
        Channel channel=ctx.channel();
        userChannelMap.put(userId, channel);
        System.out.println("用户连接容器建立成功！");
        //只用完成新消息的提醒即可，只需要获取消息的数量
        //获取RabbitMQ的消息内容，并发送给用户
        RabbitAdmin rabbitAdmin = new RabbitAdmin(rabbitTemplate);

        //--------------------------------------------------------------------------
        /*获取订阅类消息*/
        //拼接获取队列名称
        String queueName = "article_subscribe_" + userId;
        //获取Rabbit的Properties容器
        Properties queueProperties = rabbitAdmin.getQueueProperties(queueName);
        //获取消息数量
        int noticeCount = 0;
        //判断Properties是否不为空
        if (queueProperties != null) {
            noticeCount = (int) queueProperties.get("QUEUE_MESSAGE_COUNT");
            // 如果不为空，获取消息的数量
            System.out.println("订阅类有新消息:"+noticeCount);
        }
        /*------------------------------------------------------------------------*/
        //---------------以上获取订阅类消息，以下获取点赞类消息---------------------
        //拼接获取队列名称
        String userQueueName = "article_thumbup_" + userId;
        //获取Rabbit的Properties容器
        Properties userQueueProperties = rabbitAdmin.getQueueProperties(userQueueName);

        //获取消息数量
        int userNoticeCount = 0;
        //判断Properties是否不为空
        if (userQueueProperties != null) {
            userNoticeCount = (int) userQueueProperties.get("QUEUE_MESSAGE_COUNT");
            // 如果不为空，获取消息的数量
            System.out.println("用户类有新消息:"+userNoticeCount);
        }
        /*--------------------------------------------------------------------------------*/

        //获取喜欢类的消息--------------------------------------------------------------------
        //---------------以上获取订阅类消息，以下获取点赞类消息---------------------
        //拼接获取队列名称
        String loveQueueName = "gath_love_" + userId;
        //获取Rabbit的Properties容器
        Properties loveQueueProperties = rabbitAdmin.getQueueProperties(loveQueueName);

        //读取RabbitMQ中存储的消息的数量
        int loveNoticeCount = 0;
        //判断Properties是否不为空
        if (loveQueueProperties != null) {
            loveNoticeCount = (int) loveQueueProperties.get("QUEUE_MESSAGE_COUNT");
            // 如果不为空，获取消息的数量
            System.out.println("喜欢类有新消息:"+loveNoticeCount);
        }
        //-----------------------------------------------------------------------------------

        //封装返回的数据
        HashMap countMap = new HashMap();
        //订阅类消息数量
        countMap.put("sysNoticeCount", noticeCount);
        //点赞类消息数量
        countMap.put("userNoticeCount", userNoticeCount);
        //喜欢类消息数量
        countMap.put("loveNoticeCount", loveNoticeCount);

        Result result = new Result(true, StatusCode.OK, "查询成功", countMap);

        //把数据发送给用户，这是当用户第一次登录时需要返回的数据
        channel.writeAndFlush(new TextWebSocketFrame(MAPPER.writeValueAsString(result)));

        //把消息从队列里面清空，否则MQ消息监听器会再次消费一次
        if (noticeCount > 0) {
            rabbitAdmin.purgeQueue(queueName, true);
        }
        if (userNoticeCount > 0) {
            rabbitAdmin.purgeQueue(userQueueName, true);
        }
        if (loveNoticeCount > 0) {
            rabbitAdmin.purgeQueue(loveQueueName, true);
        }

        //为用户的消息通知队列注册监听器，便于用户在线的时候，
        //一旦有消息，可以主动推送给用户，不需要用户请求服务器获取数据
        if (queueProperties != null)
            sysNoticeContainer.addQueueNames(queueName);
        if (userQueueProperties != null)
            userNoticeContainer.addQueueNames(userQueueName);
        if (loveQueueProperties != null)
            loveNoticeContainer.addQueueNames(loveQueueName);
    }
}
